home *** CD-ROM | disk | FTP | other *** search
/ Click Press Kit / Click Press Kit.iso / pc / main.dxr / Internal_38_xml.parser.ls < prev    next >
Encoding:
Text File  |  2006-05-31  |  9.6 KB  |  356 lines

  1. property child, count, _ignoreWhiteSpace, _doneParsing, _cbMethod, _cbObject, _netID, _whiteSpace, _entityList, _docType, _errorStr, _idList, _tagList
  2.  
  3. on new me
  4.   me.child = []
  5.   me._ignoreWhiteSpace = 1
  6.   me._doneParsing = 1
  7.   me._errorStr = EMPTY
  8.   me._whiteSpace = SPACE & RETURN & TAB & numToChar(10)
  9.   return me
  10. end
  11.  
  12. on parseUrl me, url, cbMethod, cbObject
  13.   me._cbMethod = cbMethod
  14.   me._cbObject = cbObject
  15.   me._netID = getNetText(url)
  16.   me._doneParsing = 0
  17.   (the actorList).add(me)
  18. end
  19.  
  20. on parseString me, xmlString
  21.   me.child = []
  22.   me._idList = [:]
  23.   me._tagList = [:]
  24.   me._entityList = [:]
  25.   me._entityList.addProp("lt", "<")
  26.   me._entityList.addProp("gt", ">")
  27.   me._entityList.addProp("amp", "&")
  28.   me._entityList.addProp("apos", "'")
  29.   me._entityList.addProp("quot", QUOTE)
  30.   currentNode = me
  31.   me.count = 0
  32.   elementStack = []
  33.   xmlTokens = new(script("xml.tokenizer"), xmlString, "<>", 1)
  34.   repeat while xmlTokens.hasMoreTokens()
  35.     token = xmlTokens.nextToken()
  36.     if token = "<" then
  37.       token = xmlTokens.nextToken()
  38.       case token.char[1] of
  39.         "?":
  40.           if token.char[2..4] <> "xml" then
  41.             currentNode.child.append(me.parseProcInst(token))
  42.           end if
  43.         "!":
  44.           case token.char[1..3] of
  45.             "!DO":
  46.               me.parseDocType(token)
  47.               if token contains "[" then
  48.                 repeat while xmlTokens.hasMoreTokens()
  49.                   token = xmlTokens.nextToken()
  50.                   if token contains "]" then
  51.                     exit repeat
  52.                   end if
  53.                   case token.char[1..3] of
  54.                     "!EN":
  55.                       me.parseEntity(token)
  56.                   end case
  57.                 end repeat
  58.               end if
  59.             "!--":
  60.               repeat while xmlTokens.hasMoreTokens()
  61.                 newToken = xmlTokens.nextToken()
  62.                 if newToken = ">" then
  63.                   if token.char[token.length - 1..token.length] = "--" then
  64.                     exit repeat
  65.                   end if
  66.                 end if
  67.                 token = newToken
  68.               end repeat
  69.             "![C":
  70.               repeat while xmlTokens.hasMoreTokens()
  71.                 newToken = xmlTokens.nextToken()
  72.                 if newToken = ">" then
  73.                   if token.char[token.length - 1..token.length] = "]]" then
  74.                     textNode = me.parseCDATA(token)
  75.                     if textNode.ilk = #instance then
  76.                       currentNode.child.append(textNode)
  77.                     end if
  78.                     exit repeat
  79.                   end if
  80.                 end if
  81.                 token = token & newToken
  82.               end repeat
  83.           end case
  84.         "/":
  85.           if elementStack.count then
  86.             currentNode = elementStack[1]
  87.             elementStack.deleteAt(1)
  88.             currentNode.count = currentNode.count + 1
  89.           end if
  90.         otherwise:
  91.           if token.char[token.length] = "/" then
  92.             delete token.char[token.length]
  93.             newNode = me.parseElement(token, 1)
  94.             currentNode.child.append(newNode)
  95.             currentNode.count = currentNode.count + 1
  96.           else
  97.             elementStack.addAt(1, currentNode)
  98.             newNode = me.parseElement(token, 0)
  99.             currentNode.child.append(newNode)
  100.             currentNode = newNode
  101.             currentNode.count = 0
  102.           end if
  103.       end case
  104.       next repeat
  105.     end if
  106.     if token = ">" then
  107.       next repeat
  108.     end if
  109.     if currentNode <> me then
  110.       textNode = me.parseText(token)
  111.       if textNode.ilk = #instance then
  112.         currentNode.child.append(textNode)
  113.       end if
  114.     end if
  115.   end repeat
  116. end
  117.  
  118. on ignoreWhitespace me, ignore
  119.   me._ignoreWhiteSpace = ignore
  120. end
  121.  
  122. on doneParsing me
  123.   return me._doneParsing
  124. end
  125.  
  126. on makeList me
  127.   docList = [:]
  128.   childList = ["!ATTRIBUTES": [:]]
  129.   repeat with node in me.child
  130.     case node.type of
  131.       #element:
  132.         childList.addProp(node.name, node.toList())
  133.       #procInst:
  134.         childList.addProp("!PROCINST", node.toList())
  135.       #charData:
  136.         childList.addProp("!CHARDATA", node.toList())
  137.     end case
  138.   end repeat
  139.   if count(me.child) then
  140.     docList.addProp("ROOT OF XML DOCUMENT", childList)
  141.   end if
  142.   return docList
  143. end
  144.  
  145. on getError me
  146.   return me._errorStr
  147. end
  148.  
  149. on getAt me, index
  150.   if index.ilk = #integer then
  151.     return me.child[index]
  152.   else
  153.     index = string(index)
  154.     repeat with node in me.child
  155.       if node.name = index then
  156.         return node
  157.       end if
  158.     end repeat
  159.   end if
  160. end
  161.  
  162. on count me
  163.   return count(me.child)
  164. end
  165.  
  166. on getElementByID me, id
  167.   return me._idList[id]
  168. end
  169.  
  170. on getElementByName me, tagName
  171.   if tagName = "*" then
  172.     return me._tagList
  173.   else
  174.     elemList = me._tagList[tagName]
  175.     if elemList.count > 1 then
  176.       return elemList
  177.     else
  178.       return elemList[1]
  179.     end if
  180.   end if
  181. end
  182.  
  183. on getText me
  184.   str = EMPTY
  185.   repeat with node in me.child
  186.     str = str & node.getText()
  187.   end repeat
  188.   return str
  189. end
  190.  
  191. on makeDocument me
  192.   xmlDoc = "<?xml version=" & QUOTE & "1.0" & QUOTE & "?>" & RETURN
  193.   repeat with node in me.child
  194.     xmlDoc = xmlDoc & node.toString() & RETURN
  195.   end repeat
  196.   return xmlDoc
  197. end
  198.  
  199. on stepFrame me
  200.   if netDone(me._netID) then
  201.     if netError(me._netID) = "OK" then
  202.       xmlDoc = netTextResult(me._netID)
  203.       me.parseString(xmlDoc)
  204.     else
  205.       me._errorStr = "net error:" && netError(me._netID)
  206.     end if
  207.     me._doneParsing = 1
  208.     if me._cbMethod.ilk <> #void then
  209.       if me._cbObject.ilk = #void then
  210.         do(me._cbMethod && "me")
  211.       else
  212.         call(me._cbMethod, me._cbObject, me)
  213.       end if
  214.     end if
  215.   end if
  216. end
  217.  
  218. on parseProcInst me, tokenStr
  219.   delete tokenStr.char[tokenStr.length]
  220.   delete tokenStr.char[1]
  221.   piName = tokenStr.word[1]
  222.   piData = tokenStr.word[2..tokenStr.word.count]
  223.   piNode = new(script("xml.node"), piName, #procInst, piData)
  224.   return piNode
  225. end
  226.  
  227. on parseDocType me, tokenStr
  228.   me._docType = tokenStr.word[2]
  229. end
  230.  
  231. on parseEntity me, tokenStr
  232.   entityName = tokenStr.word[2]
  233.   if entityName <> "%" then
  234.     entityValue = tokenStr.word[3..tokenStr.word.count]
  235.     delete entityValue.char[entityValue.length]
  236.     delete entityValue.char[1]
  237.     entityValue = me.decodeEntities(entityValue)
  238.     if not me._entityList.findPos(entityName) then
  239.       me._entityList.addProp(entityName, entityValue)
  240.     end if
  241.   end if
  242. end
  243.  
  244. on parseCDATA me, tokenStr
  245.   delete tokenStr.char[tokenStr.length - 1..tokenStr.length]
  246.   delete tokenStr.char[1..8]
  247.   if tokenStr.length then
  248.     return new(script("xml.node"), VOID, #charData, tokenStr)
  249.   else
  250.     return VOID
  251.   end if
  252. end
  253.  
  254. on parseElement me, tokenStr, isEmpty
  255.   elementName = tokenStr.word[1]
  256.   elementNode = new(script("xml.node"), elementName, #element, VOID)
  257.   elementNode.isEmpty = isEmpty
  258.   if offset("=", tokenStr) then
  259.     attributeStr = tokenStr.word[2..tokenStr.word.count]
  260.     attributeList = me.parseAttributes(attributeStr)
  261.     elementNode.attributeValue = attributeList
  262.     numAttributes = attributeList.count
  263.     repeat with i = 1 to numAttributes
  264.       elementNode.attributeName.append(attributeList.getPropAt(i))
  265.     end repeat
  266.     if attributeList.findPos("id") then
  267.       me._idList.setaProp(attributeList["id"], elementNode)
  268.     end if
  269.   end if
  270.   if not me._tagList.findPos(elementName) then
  271.     me._tagList.addProp(elementName, [elementNode])
  272.   else
  273.     tagList = me._tagList[elementName]
  274.     tagList.append(elementNode)
  275.   end if
  276.   return elementNode
  277. end
  278.  
  279. on parseAttributes me, attrStr
  280.   attrList = [:]
  281.   attrTokens = new(script("xml.tokenizer"), attrStr, QUOTE & "'=" & me._whiteSpace, 1)
  282.   repeat while attrTokens.hasMoreTokens()
  283.     token = attrTokens.nextToken()
  284.     repeat while me._whiteSpace contains token
  285.       token = attrTokens.nextToken()
  286.     end repeat
  287.     attrName = token
  288.     repeat while token <> "="
  289.       token = attrTokens.nextToken()
  290.     end repeat
  291.     quoteType = attrTokens.nextToken()
  292.     repeat while (quoteType <> "'") and (quoteType <> QUOTE)
  293.       quoteType = attrTokens.nextToken()
  294.     end repeat
  295.     token = attrTokens.nextToken()
  296.     attrValue = EMPTY
  297.     repeat while token <> quoteType
  298.       attrValue = attrValue & token
  299.       token = attrTokens.nextToken()
  300.     end repeat
  301.     attrValue = me.decodeEntities(attrValue)
  302.     attrList.addProp(attrName, attrValue)
  303.   end repeat
  304.   return attrList
  305. end
  306.  
  307. on parseText me, tokenStr
  308.   textStr = EMPTY
  309.   if me._ignoreWhiteSpace then
  310.     tokens = new(script("xml.tokenizer"), tokenStr, me._whiteSpace)
  311.     if tokens.hasMoreTokens() then
  312.       textStr = me.decodeEntities(tokens.nextToken())
  313.     end if
  314.     repeat while tokens.hasMoreTokens()
  315.       textToken = tokens.nextToken()
  316.       textStr = textStr && me.decodeEntities(textToken)
  317.     end repeat
  318.   else
  319.     textStr = me.decodeEntities(tokenStr)
  320.   end if
  321.   if textStr.length then
  322.     return new(script("xml.node"), VOID, #charData, textStr)
  323.   else
  324.     return VOID
  325.   end if
  326. end
  327.  
  328. on decodeEntities me, str
  329.   if offset("&", str) and offset(";", str) then
  330.     tokens = new(script("xml.tokenizer"), str, "&;", 1)
  331.     decodedStr = EMPTY
  332.     repeat while tokens.hasMoreTokens()
  333.       token = tokens.nextToken()
  334.       if token = "&" then
  335.         entityName = tokens.nextToken()
  336.         if entityName.char[1] = "#" then
  337.           if entityName.char[2] = "x" then
  338.             entityValue = numToChar(rgb(entityName.char[3..4] & "FFFF").red)
  339.           else
  340.             entityValue = numToChar(entityName.value)
  341.           end if
  342.         else
  343.           entityValue = me._entityList.getaProp(entityName)
  344.         end if
  345.         decodedStr = decodedStr & entityValue
  346.         tokens.nextToken()
  347.         next repeat
  348.       end if
  349.       decodedStr = decodedStr & token
  350.     end repeat
  351.     return decodedStr
  352.   else
  353.     return str
  354.   end if
  355. end
  356.